package com.baicaoyuan.web.service;

import com.baicaoyuan.web.common.*;
import com.baicaoyuan.web.enums.*;
import com.baicaoyuan.web.model.*;
import com.baicaoyuan.web.repository.*;
import com.baicaoyuan.web.request.br.BAddAccountRequest;
import com.baicaoyuan.web.request.br.BAddLotteryScoreRequest;
import com.baicaoyuan.web.request.br.BAddressRequest;
import com.baicaoyuan.web.response.JzzUserSimpleResponse;
import com.baicaoyuan.web.response.ProjectItemUserResultResponse;
import com.baicaoyuan.web.response.UserResponse;
import com.baicaoyuan.web.response.UserSimpleResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

/**
 * 功能描述：
 *
 * @author 罗富祥
 * 创建时间： 2018/1/4
 */
@Service
public class UserService {

    @Autowired
    UserRepository userRepository;

    @Autowired
    ScoreDetailService scoreDetailService;

    @Autowired
    StockInRepository stockInRepository;

    @Autowired
    VerificationCodeRepository verificationCodeRepository;

    @Autowired
    InvitationCodeUtil invitationCodeUtil;

    @Autowired
    ContributionValueConfig contributionValueConfig;

    @Autowired
    JzzUserProjectRepository jzzUserProjectRepository;

    @Autowired
    ProjectItemUserRepository projectItemUserRepository;

    @Autowired
    ProjectItemRepository projectItemRepository;

    @Autowired
    ProjectRepository projectRepository;

    public List<UserDO> findByStatusAndType() {
        return userRepository.findByStatusAndType("1", 1);
    }


    public boolean addAccount(BAddAccountRequest request) {
        UserDO user = userRepository.getOne(request.getUserId());
        if (request.getAliPayInfo() != null) {
            user.setAlipay(FastJsonUtils.object2JsonString(request.getAliPayInfo()));
        } else {
            user.setAlipay(null);
        }
        if (request.getBankInfo() != null) {
            user.setBank(FastJsonUtils.object2JsonString(request.getBankInfo()));
        } else {
            user.setBank(null);
        }

        return userRepository.save(user) != null;
    }

    public boolean addAddress(BAddressRequest addressRequest) {
        UserDO user = userRepository.getOne(addressRequest.getUserId());
        if (user != null) {
            user.setProvince(addressRequest.getProvince());
            user.setCity(addressRequest.getCity());
            user.setArea(addressRequest.getArea());
            user.setAddress(addressRequest.getAddress());

            return userRepository.save(user) != null;
        } else {
            return false;
        }

    }

    /**
     * 获取验证码
     *
     * @param telephone
     * @return
     */
    public String getVerification(String telephone) {
        VerificationCodeDo verificationCodeDo = verificationCodeRepository.findByTelephone(telephone);
        if (verificationCodeDo == null) {
            return null;
        }
        return verificationCodeDo.getVerification_code();
    }

    /**
     * 保存验证码信息
     *
     * @param telephone        手机号
     * @param verificationCode 验证码
     */
    public void saveVerification(String telephone, String verificationCode) {
        VerificationCodeDo code = new VerificationCodeDo(telephone, verificationCode);
        Objects.requireNonNull(this.verificationCodeRepository.save(code));
    }

    public void save(UserDO user) {
        Objects.requireNonNull(this.userRepository.save(user));
    }

    /**
     * 更新token
     *
     * @param id
     * @param token
     */
    public void updateToken(Long id, String token) {
        Integer result = this.userRepository.updateToken(id, token);
        if (result < 1) {
            throw new RuntimeException();
        }
    }

    /**
     * 删除用户
     *
     * @param id
     */
    public void delete(Long id) {
        Integer result = this.userRepository.updateStatus(id, StatusEnum.DELETE.getStatus());
        if (result <= 0) {
            throw new RuntimeException();
        }
    }

    /**
     * 移除股东
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    public void removeUserOutStock(Long id) {
        UserDO u = this.userRepository.getOne(id);
        float t = u.getContributionValueTotal().floatValue();
        String category = t > 0.5 ? "2" : "1";
        Integer result = this.userRepository.setCategory(id, category);
        if (result > 0) {
            stockInRepository.deleteByUserIdFk(id);
        }
    }

    public Integer getCountOfAll(String telephone, String category) {
        return this.userRepository.countAllByStatusIsNotAndTelephoneLikeAndCategoryLike(StatusEnum.DELETE.getStatus(), StringUtils.plusPercent(telephone), StringUtils.plusPercent(category));
    }

    public Long getCountOfUserDirectId(Long userDirectId) {
        return this.userRepository.countByUserDirectId(userDirectId);
    }

    /**
     * 根据直接推荐人id， 获取所发展的下线
     *
     * @param userDirectId
     * @return
     */
    public List<UserSimpleResponse> findByUserDirectId(Long userDirectId) {
        List<UserSimpleResponse> result = new ArrayList<>();
        List<UserDO> list = this.userRepository.findByUserDirectId(userDirectId);
        list.forEach(x -> {
            UserSimpleResponse usr = new UserSimpleResponse();
            BeanUtils.copyProperties(x, usr);
            usr.setDownLine(getCountOfUserDirectId(usr.getId()));
            result.add(usr);
        });
        return result;
    }

    /**
     * 获取一个用户下直推的金种子用户和间推的金种子用户
     *
     * @param userId
     * @return
     */
    public List<JzzUserSimpleResponse> findOwnJzzUserByUserDirectIdAndInDirectId(Long userId) {

        List<JzzUserSimpleResponse> result = new ArrayList<>();
        List<UserDO> directUsers = userRepository.findByUserDirectIdAndType(userId, 1);
        directUsers.forEach(x -> {
            JzzUserSimpleResponse usr = new JzzUserSimpleResponse();
            BeanUtils.copyProperties(x, usr);
            result.add(usr);

            List<JzzUserSimpleResponse> indirectList = new ArrayList<>();
            //获取间推
            List<UserDO> indirectUsers = userRepository.findByUserIndirectIdAndType(userId, 1);
            if (!CollectionUtils.isEmpty(indirectUsers)) {
                indirectUsers.forEach(y -> {
                    JzzUserSimpleResponse iUser = new JzzUserSimpleResponse();
                    BeanUtils.copyProperties(y, iUser);
                    indirectList.add(iUser);
                });
            }
            usr.setIndirectUsers(indirectList);
        });
        return result;
    }

    public List<UserResponse> getUsers(String telephone, String category, Integer page, Integer size) {
        List<UserDO> users = this.userRepository.getUsers(telephone, category, (page - 1) * size, size);
        List<UserResponse> result = new ArrayList<>();
        users.stream().forEach(x -> {
            UserResponse ur = new UserResponse();
            x.setDownlineNumber(getCountOfUserDirectId(x.getId()));
            BeanUtils.copyProperties(x, ur);

            if (x.getUserDirectId() != null) {
                UserDO directUser = this.userRepository.getOne(x.getUserDirectId());
                if ("1".equals(directUser.getStatus())) {
                    UserSimpleResponse userSimple = new UserSimpleResponse();
                    BeanUtils.copyProperties(directUser, userSimple);
                    ur.setUserDirect(userSimple);
                }
            }

            if (x.getCategory().equals("3")) {
                Long stockNumber = 0L;
                List<StockInDO> l = stockInRepository.getStockIn(x.getId());
                if (l != null) {
                    for (StockInDO s : l) {
                        stockNumber += s.getStockNumber();
                    }
                    ur.setStockNumber(stockNumber);
                }
            }


            result.add(ur);
        });
        return result;
    }

    /**
     * 核对token
     *
     * @param id
     * @param token
     * @return
     */
    public boolean checkToken(Long id, String token) {
        UserDO user = this.userRepository.getOne(id);
        if (!"1".equals(user.getStatus()))
            return false;
        return token.equals(user.getToken());
    }

    /**
     * 保存注册用户
     *
     * @param telephone
     * @param password
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveUser(String telephone, String password, String invitationCode, String realName, String card) {
        UserDO user = new UserDO();
        user.setTelephone(telephone);
        user.setPassword(password);
        user.setRealName(realName);
        user.setCard(card);
        user.setScore(0);
        UserDO u = this.userRepository.save(user);

        Objects.requireNonNull(u);
        u.setInvitationCode(invitationCodeUtil.generate_invitation_code(u.getId()));
        u.setCreateTime(TimeUtils.getCurrentTime());
        u.setStatus(StatusEnum.NORMAL.getStatus());
        u.setCategory(UserCategoryEnum.NO_VIP.getStatus());
        u.setBusiness(UserBusinessEnum.GENERAL.getStatus());
        u.setWebAdmin(ClientTypeEnum.WAP.getStatus());
        u.setType(0);
        if (StringUtils.isNotNullAndEmpty(invitationCode)) {
            //设置直接介绍人
            UserDO x = userRepository.findByInvitationCode(invitationCode);
            u.setUserDirectId(x.getId());
            //设置间接介绍人
            if (Objects.nonNull(x.getUserDirectId())) {
                u.setUserIndirectId(x.getUserDirectId());
            }
        }
        u.setContributionValueTotal(contributionValueConfig.getRegister());
        u.setScoreTotal(BigDecimal.ZERO);
        u = this.userRepository.save(u);

        Objects.requireNonNull(u);

        //注册直接介绍人获得积分
        registerPlus(u.getId());
    }

    /**
     * 根据邀请码获取对应的客户
     *
     * @param invitationCode
     * @return
     */
    public UserDO getUserByInvitationCode(String invitationCode) {
        return userRepository.findByInvitationCode(invitationCode);
    }

    public UserDO findOne(Long userId) {
        return this.userRepository.findOne(userId);
    }

    /**
     * 根据手机号获取用户
     *
     * @param telephone
     * @return
     */
    public UserDO getUserByTelephone(String telephone) {
        return this.userRepository.findByTelephone(telephone);
    }

    /**
     * 根据id获取用户详情
     *
     * @param userId
     * @return
     */
    public UserResponse getUserById(Long userId) {
        UserDO i = this.userRepository.findOne(userId);

        UserResponse ir = new UserResponse();
        BeanUtils.copyProperties(i, ir);

        List<ProjectItemUserDO> list = projectItemUserRepository.findByUserIdAndStatusNot(userId, ApplyStatusEnum.DELETED.getStatus());
        list = list.stream().filter(x -> {
            return projectItemRepository.findOne(x.getProjectItemId()).getStatus().equals("1");
        }).collect(Collectors.toList());

        Map<Long, ProjectItemUserDO> map = list.stream().sorted(Comparator.comparing(ProjectItemUserDO::getCreateTime).reversed()).collect(groupingBy(ProjectItemUserDO::getProjectId, Collectors.collectingAndThen(Collectors.toList(), value -> value.get(0))));
        if (!CollectionUtils.isEmpty(map)) {
            List<ProjectItemUserResultResponse> list1 = new ArrayList<>();
            map.forEach((projectId, piu) -> {
                ProjectDO projectDO = projectRepository.findOne(piu.getProjectId());
                if (projectDO.getJoinJzz() == 1 && !StringUtils.isNullOrEmpty(piu.getStatus())) {
                    ProjectItemUserResultResponse pur = new ProjectItemUserResultResponse(piu.getProjectId(), piu.getRejectReason(), piu.getStatus());
                    list1.add(pur);
                }
            });

            ir.setProjectIdStatus(list1);
        }
        if (i.getUserDirectId() != null) {
            ir.setUserDirect(getSimpleUser(i.getUserDirectId()));
        }
        if (i.getUserIndirectId() != null) {
            ir.setUserIndirect(getSimpleUser(i.getUserIndirectId()));
        }

        if (i.getCategory().equals("3")) {
            Long stockNumber = 0L;
            List<StockInDO> l = stockInRepository.getStockIn(i.getId());
            if (l != null) {
                for (StockInDO s : l) {
                    stockNumber += s.getStockNumber();
                }
                ir.setStockNumber(stockNumber);
            }
        }

        return ir;
    }

    public UserSimpleResponse getSimpleUser(Long userId) {
        UserDO userDO = this.userRepository.findOne(userId);
        UserSimpleResponse usp = new UserSimpleResponse();
        BeanUtils.copyProperties(userDO, usp);
        return usp;
    }

    /**
     * 注册(直接要求一个用户)加分（0.5）
     *
     * @param userId
     */
    @Transactional(rollbackFor = Exception.class)
    public void registerPlus(Long userId) {
        Objects.requireNonNull(userId);
        BigDecimal registerValue = contributionValueConfig.getRegister();
        System.out.println(registerValue);
        UserDO u = userRepository.findOne(userId);
        if (StringUtils.isNotNullAndGreater0(u.getUserDirectId())) {
            Integer r = userRepository.plusContribution(u.getUserDirectId(), registerValue);
            if (r <= 0) {
                throw new RuntimeException();
            }
        }

    }

    /**
     * 成功办理业务加分（贡献分）
     * 其直接介绍人也加分（贡献分）
     *
     * @param userId
     * @param contributionValue 贡献分值
     */
    @Transactional(rollbackFor = Exception.class)
    public void contributeValuePlus(Long userId, BigDecimal contributionValue) {
        Objects.requireNonNull(userId);
        Objects.requireNonNull(contributionValue);

        UserDO u = userRepository.findOne(userId);

        if (StringUtils.isNotNullAndGreater0(u.getUserDirectId())) {
            //如果直接介绍人
            UserDO directUser = userRepository.findOne(u.getUserDirectId());
            //且该直接介绍人为VIP，则加贡献分
            if (UserCategoryEnum.VIP.getStatus().equals(directUser.getCategory())) {
                Integer r = userRepository.plusContribution(u.getUserDirectId(), contributionValue);
                if (r <= 0) {
                    throw new RuntimeException();
                }
            }
        }
        //如果业务办理人是vip，则添加分数
        if (UserCategoryEnum.VIP.getStatus().equals(u.getCategory())) {
            Integer c = userRepository.plusContribution(userId, contributionValue);
            if (c <= 0) {
                throw new RuntimeException();
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void setVip(Long userId) {

        UserDO user = this.userRepository.findOne(userId);
        //如果该用户已经成为了Vip，则不再做处理
        if (UserCategoryEnum.VIP.getStatus().equals(user.getCategory())) {
            return;
        } else {
            userRepository.setCategory(user.getId(), UserCategoryEnum.VIP.getStatus());
        }
        //判断其直接介绍人是否为Vip
        if (StringUtils.isNotNullAndGreater0(user.getUserDirectId())) {
            UserDO d = userRepository.findOne(user.getUserDirectId());
            if (!UserCategoryEnum.VIP.getStatus().equals(d.getCategory())) {
                //如果直接人还不是vip， 则设置成vip
                userRepository.setCategory(d.getId(), UserCategoryEnum.VIP.getStatus());
            }
        }
    }

    public void scorePlus(Long userId, BigDecimal score) {
        Integer result = this.userRepository.plusScore(userId, score);
        if (result <= 0) {
            throw new RuntimeException();
        }
    }

    /**
     * 增减抽奖积分
     *
     * @param userId
     * @param score
     * @return
     */
    public boolean addOrReduceLotteryScore(Long userId, Integer score) {
        boolean r = false;
        UserDO user = this.userRepository.getOne(userId);
        if (user != null) {

            user.setScore((user.getScore() == null ? 0 : user.getScore()) + score);
            r = this.userRepository.save(user) != null;
        }
        return r;
    }


    @Transactional
    public boolean addLotteryScore(BAddLotteryScoreRequest request) {
        if (request.getUserId2ScoreList() == null || request.getUserId2ScoreList().size() == 0) {
            throw new RuntimeException("参数未空！请检查！");
        }

        List<UserDO> userDOList = new ArrayList<>();
        request.getUserId2ScoreList().forEach(x -> {
            UserDO user = this.userRepository.getOne(x.getId());
            if (user == null) {
                throw new RuntimeException("用户不存在,id =" + x.getId());
            }
            Integer score = (user.getScore() == null ? 0: user.getScore())+ x.getScore();
            user.setScore(score);
            userDOList.add(user);
        });

        return this.userRepository.save(userDOList).size() > 0;
    }
}

